package websocket

import (
	"context"
	"errors"
	"fmt"
	"log"
	"net/http"
	"os"
	"os/signal"
	"sync"
	"syscall"
	"time"

	"gitee.com/dreamwithouttrace/websocket-module/core"
	"gitee.com/dreamwithouttrace/websocket-module/handlers"
	"gitee.com/dreamwithouttrace/websocket-module/middleware"
	"gitee.com/dreamwithouttrace/websocket-module/transport"
	"github.com/go-redis/redis"
	"gorm.io/gorm"

	"github.com/gorilla/mux"
)

// Server WebSocket服务器
type Server struct {
	config    *core.Config
	transport *transport.Transport
	handshake *handlers.HandshakeHandler
	api       *handlers.APIHandler
	auth      *middleware.AuthMiddleware
	test      *middleware.TestClientMiddleware
	rateLimit *middleware.RateLimitMiddleware
	server    *http.Server
	router    *mux.Router
	redis     *redis.Client // Redis客户端接口
	db        *gorm.DB      // 数据库接口
	waitGroup sync.WaitGroup
	isRunning bool
	mu        sync.RWMutex
}

// NewServer 创建新的WebSocket服务器
func NewServer(config *core.Config, redis *redis.Client, db *gorm.DB, queryFunc func(db *gorm.DB, token string) (core.User, error)) *Server {
	// 创建传输管理器
	newTransport := transport.NewTransport(config)

	// 创建处理器
	handshake := handlers.NewHandshakeHandler(newTransport, config, redis)
	api := handlers.NewAPIHandler(newTransport, config)

	// 创建中间件
	// 注意：现在必须提供自定义查询函数
	// 示例查询函数（实际使用时需要根据你的数据库结构实现）
	auth := middleware.NewAuthMiddleware(redis, db, queryFunc) // 需要实现查询函数
	test := middleware.NewTestClientMiddleware(db, queryFunc)  // 需要实现查询函数

	rateLimit := middleware.NewRateLimitMiddleware(redis, 100, time.Minute)

	return &Server{
		config:    config,
		transport: newTransport,
		handshake: handshake,
		api:       api,
		auth:      auth,
		test:      test,
		rateLimit: rateLimit,
		router:    mux.NewRouter(),
		redis:     redis,
		db:        db,
		isRunning: false,
	}
}

// SetCallbacks 设置回调函数
func (s *Server) SetCallbacks(
	onDisconnect func(conn core.Connection, user core.User, role interface{}),
	onMessage func(conn core.Connection, user core.User, role interface{}, message []byte),
	onConnect func(conn core.Connection) error,
	onMinuteCallback func(boyTotal, girlTotal, noSexTotal, total int64),
	onDeliveryFailure func(data core.Message),
) {
	s.transport.SetCallbacks(onDisconnect, onMessage, onConnect, onMinuteCallback, onDeliveryFailure)
}

// Start 启动服务器
func (s *Server) Start() error {
	s.mu.Lock()
	defer s.mu.Unlock()

	if s.isRunning {
		return fmt.Errorf("服务器已在运行")
	}

	// 设置路由
	s.setupRoutes(s.router)

	// 创建HTTP服务器
	s.server = &http.Server{
		Addr:           fmt.Sprintf("%s:%d", s.config.Host, s.config.Port),
		Handler:        s.router,
		ReadTimeout:    30 * time.Second,
		WriteTimeout:   30 * time.Second,
		MaxHeaderBytes: s.config.MaxHeaderBytes,
	}

	s.isRunning = true

	// 启动服务器
	go func() {
		log.Printf("WebSocket服务器启动在 %s", s.server.Addr)
		if err := s.server.ListenAndServe(); err != nil && !errors.Is(err, http.ErrServerClosed) {
			log.Printf("服务器启动失败: %v", err)
		}
	}()

	// 启动统计协程
	go s.startStatistics()

	return nil
}

// Stop 停止服务器
func (s *Server) Stop() error {
	s.mu.Lock()
	defer s.mu.Unlock()

	if !s.isRunning {
		return nil
	}

	log.Println("正在关闭WebSocket服务器...")

	// 停止传输管理器
	s.transport.Stop(true)

	// 创建关闭上下文
	ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
	defer cancel()

	// 关闭HTTP服务器
	if err := s.server.Shutdown(ctx); err != nil {
		log.Printf("关闭服务器时出错: %v", err)
	}

	s.isRunning = false
	log.Println("WebSocket服务器已关闭")

	return nil
}

func (s *Server) AddRouter(method, path string, handler func(http.ResponseWriter, *http.Request)) {
	s.router.HandleFunc(path, handler).Methods(method)
}

// setupRoutes 设置路由
func (s *Server) setupRoutes(router *mux.Router) {
	// WebSocket连接路由
	router.HandleFunc("/ws", s.handleWebSocket)
	router.HandleFunc("/test-ws", s.handleTestWebSocket)

	// API路由
	router.HandleFunc("/kick", s.api.Kick).Methods("GET")
	router.HandleFunc("/online/lists", s.api.OnlineLists).Methods("GET")
	router.HandleFunc("/get/online", s.api.OnlineInfo).Methods("GET")
	router.HandleFunc("/check/content", s.api.CheckContent).Methods("GET")
	router.HandleFunc("/check/content", s.api.PostCheckContent).Methods("POST")
	router.HandleFunc("/statistics", s.api.Statistics).Methods("GET")
}

// handleWebSocket 处理WebSocket连接
func (s *Server) handleWebSocket(w http.ResponseWriter, r *http.Request) {
	// 应用限流中间件
	var err error
	if _, err = s.rateLimit.Process(w, r); err != nil {
		log.Println(err.Error(), http.StatusTooManyRequests)

		http.Error(w, err.Error(), http.StatusTooManyRequests)
		return
	}

	// 应用认证中间件
	var user core.User
	if user, err = s.auth.Process(s.config, r); err != nil {
		log.Println(err.Error(), http.StatusUnauthorized)

		http.Error(w, err.Error(), http.StatusUnauthorized)
		return
	}

	// 处理握手
	if err := s.handshake.Handshake(user, s.getClientIP(r), w, r); err != nil {
		log.Println(err.Error(), http.StatusInternalServerError)

		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}
}

// handleTestWebSocket 处理测试WebSocket连接
func (s *Server) handleTestWebSocket(w http.ResponseWriter, r *http.Request) {
	// 应用测试客户端中间件
	var user core.User
	var err error
	if user, err = s.test.Process(s.config, r); err != nil {
		log.Println(err.Error(), http.StatusUnauthorized)

		http.Error(w, err.Error(), http.StatusUnauthorized)
		return
	}

	// 处理握手
	if err := s.handshake.Handshake(user, s.getClientIP(r), w, r); err != nil {
		log.Println(err.Error(), http.StatusInternalServerError)

		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}
}

// getClientIP 获取客户端IP
func (s *Server) getClientIP(r *http.Request) string {
	// 获取X-Forwarded-For头
	if xff := r.Header.Get("X-Forwarded-For"); xff != "" {
		return xff
	}

	// 获取X-Real-IP头
	if xri := r.Header.Get("X-Real-IP"); xri != "" {
		return xri
	}

	// 获取RemoteAddr
	return r.RemoteAddr
}

// startStatistics 启动统计协程
func (s *Server) startStatistics() {
	ticker := time.NewTicker(1 * time.Minute)
	defer ticker.Stop()

	for {
		select {
		case <-ticker.C:
			s.transport.OnlineUserInformationStatistics()
		}
	}
}

func (s *Server) Clean() {
	s.transport.Clear()
}

// Send 发送消息给指定用户
func (s *Server) Send(user int64, message core.Message) {
	s.transport.Push(user, message)
}

// SendAll 发送消息给所有
func (s *Server) SendAll(message core.Message) {
	s.transport.BatchPush(message)
}

// GetUser 根据ID获取玩家
func (s *Server) GetUser(id int64) *core.WebSocketConnection {
	return s.transport.Get(id)
}

// Run 运行服务器（阻塞）
func (s *Server) Run() error {
	if err := s.Start(); err != nil {
		return err
	}

	// 等待中断信号
	ch := make(chan os.Signal, 1)
	signal.Notify(ch, syscall.SIGTERM, syscall.SIGQUIT, syscall.SIGINT)
	sig := <-ch

	log.Printf("收到信号: %s", sig.String())

	return s.Stop()
}

// GetTransport 获取传输管理器
func (s *Server) GetTransport() *transport.Transport {
	return s.transport
}

// GetConfig 获取配置
func (s *Server) GetConfig() *core.Config {
	return s.config
}

// IsRunning 检查服务器是否运行
func (s *Server) IsRunning() bool {
	s.mu.RLock()
	defer s.mu.RUnlock()
	return s.isRunning
}
